#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "fuzzykmeans.h"
#define re register int 
#define in inline
#define maxn 300005

double dist2(double* v0,double* v1)
{
	return (v0[0]-v1[0])*(v0[0]-v1[0])+(v0[1]-v1[1])*(v0[1]-v1[1]);
}
double weight(double* v1,double* centers,int j,int k)
{
	double ans=0;
	re l;
	for(l=0;l<=k-1;l++){
		ans+=dist2(v1,centers+2*j)/dist2(v1,centers+2*l);
	}
	return 1/ans;
}
void fuzzykmeans(double* data, int n, double* centers, int k)
{
	double *cc ;
	cc=(double *)calloc(2*k,sizeof(double));
	//double cc[2*k];
	re i,j;
	double tmpw;
	double upx,upy,dw;
	for(j=0;j<k;j++){//calculate cc[j]
		upx=upy=dw=0;
		for(i=0;i<n;i++){//calculate w[i][j]
			tmpw=pow(weight(data+2*i,centers,j,k),2);
			upx+=data[2*i]*tmpw;
			upy+=data[2*i+1]*tmpw;
			dw+=tmpw;
		}
		cc[2*j]=upx/dw;
		cc[2*j+1]=upy/dw;
	}
	for(j=0;j<2*k;j++) centers[j]=cc[j];
	free(cc);
}

void fuzzykmeans_mpi(double* data, int n, double* centers, int k, int myid, int r)
{
    double *cc ;
    cc=(double *)calloc(2*k,sizeof(double));
    //double cc[2*k];
    re i,j,q;
    double tmpw;
    double upx,upy,dw;
    double set_xyd[3] = {0};
    double (*all_set)[3]=(double (*)[3])calloc(r, sizeof(set_xyd));

    for(j=0;j<k;j++){//calculate cc[j]
        upx=upy=dw=0;
        for(i=0;i<n;i++){//calculate w[i][j]
            tmpw=pow(weight(data+2*i,centers,j,k),2);
            upx+=data[2*i]*tmpw;
            upy+=data[2*i+1]*tmpw;
            dw+=tmpw;
        }

        all_set[myid][0] = set_xyd[0] = upx;
        all_set[myid][1] = set_xyd[1] = upy;
        all_set[myid][2] = set_xyd[2] = dw;

        for(q=0;q<r;q++){
            if(q == myid)
                continue;
            MPI_Send(set_xyd, sizeof(set_xyd)/sizeof(set_xyd[0]), MPI_DOUBLE, q, 0, MPI_COMM_WORLD);
        }
        for(q=0;q<r;q++){
            if(q == myid)
                continue;
            MPI_Recv(all_set[q], sizeof(all_set[0])/sizeof(all_set[0][0]), MPI_DOUBLE, q, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        }

        upx=upy=dw=0;
        for(q=0;q<r;q++){
            upx+=all_set[q][0];
            upy+=all_set[q][1];
            dw+=all_set[q][2];
        }

        cc[2*j]=upx/dw;
        cc[2*j+1]=upy/dw;
    }
    for(j=0;j<2*k;j++) centers[j]=cc[j];
    free(all_set);
    free(cc);
}

/*



*/

